package org.black.missedCall2;

import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.black.missedCall2.object.CallInformation;

import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.PhoneLookup;
import android.support.v4.util.LruCache;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;

public class MissedCallAdapter extends BaseAdapter {
	private static final Long MINUTE_IN_MILLISECONDS = 60 * 1000l;
	private static final Long HOUR_IN_MILLISECONDS = 60 * MINUTE_IN_MILLISECONDS;
	private static final Long DAY_IN_MILLISECONDS = 24 * HOUR_IN_MILLISECONDS;
	private static final String IMPOSSIBLE_CONTACT_ID = "-1";

	private Context context;
	private LayoutInflater layoutInflater;
	private List<CallInformation> callInformations;
	private LruCache<String, Bitmap> mMemoryCache;

	private Bitmap defaultContactPictre = null;

	public MissedCallAdapter(Context context) {
		super();
		this.context = context;
		this.layoutInflater = LayoutInflater.from(context);
		this.callInformations = new ArrayList<CallInformation>();
		this.mMemoryCache = new LruCache<String, Bitmap>(4096);
		this.defaultContactPictre = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH ? BitmapFactory
				.decodeResource(context.getResources(),
						R.drawable.ic_contact_picture) : BitmapFactory
				.decodeResource(context.getResources(),
						R.drawable.ic_contact_picture_2);
	}

	public MissedCallAdapter(Context context,
			List<CallInformation> callInformations) {
		this(context);
		if (this.callInformations != null) {
			this.callInformations.clear();
			this.callInformations = null;
		}
		this.callInformations = callInformations;
	}

	@Override
	public int getCount() {
		return this.callInformations.size();
	}

	@Override
	public Object getItem(int position) {
		return this.callInformations.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	public boolean addItem(CallInformation callInformation) {
		if (this.callInformations == null) {
			this.callInformations = new ArrayList<CallInformation>();
		}
		return this.callInformations.add(callInformation);
	}

	public boolean removeItem(CallInformation callInformation) {
		if (this.callInformations == null) {
			this.callInformations = new ArrayList<CallInformation>();
		}
		return this.callInformations.remove(callInformation);
	}

	public CallInformation removeItem(int position) {
		if (this.callInformations == null) {
			this.callInformations = new ArrayList<CallInformation>();
		}
		return this.callInformations.remove(position);
	}

	public void reset(List<CallInformation> callInformations) {
		this.callInformations.clear();
		this.callInformations.addAll(callInformations);
	}

	public void reset() {
		if (this.callInformations == null) {
			this.callInformations = new ArrayList<CallInformation>();
		}
		this.callInformations.clear();
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder viewHolder = null;
		final CallInformation callInformation = (CallInformation) this
				.getItem(position);
		Long currentTime = System.currentTimeMillis();
		if (convertView == null) {
			convertView = this.layoutInflater.inflate(R.layout.missed_call_row,
					null);
			viewHolder = new ViewHolder();

			TextView nameTextView = (TextView) convertView
					.findViewById(R.id.missedCallName);
			viewHolder.nameTextView = nameTextView;

			TextView numberTextView = (TextView) convertView
					.findViewById(R.id.missedCallNumber);
			viewHolder.numberTextView = numberTextView;

			TextView dateTextView = (TextView) convertView
					.findViewById(R.id.missedCallDateTime);
			viewHolder.dateTextView = dateTextView;

			ImageView missedCallContactImageView = (ImageView) convertView
					.findViewById(R.id.missedCallRowPhotoImageView);
			viewHolder.missedCallContactImageView = missedCallContactImageView;

			ImageButton callButton = (ImageButton) convertView
					.findViewById(R.id.callMissedCallButton);
			viewHolder.callButton = callButton;
			viewHolder.callButton
					.setOnClickListener(new View.OnClickListener() {

						public void onClick(View v) {
							Uri uri = Uri.parse("tel:"
									+ callInformation.getNumber());
							Intent intent = new Intent(Intent.ACTION_CALL, uri);
							intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
							layoutInflater.getContext().startActivity(intent);
						}
					});
			convertView.setTag(viewHolder);
		} else {
			viewHolder = (ViewHolder) convertView.getTag();
		}
		SharedPreferences sharedPreferences = PreferenceManager
				.getDefaultSharedPreferences(context.getApplicationContext());

		float scale = (sharedPreferences
				.getInt(convertView
						.getResources()
						.getString(
								R.string.seek_bar_position_for_font_size_preference_key),
						MissedCallFontSizeDialogFragment.DEFAULT_SEEK_BAR_VALUE) / (float) MissedCallFontSizeDialogFragment.SEEK_BAR_MAX_VALUE) + 1;
		float headerSize = MissedCallConstant.FONT_SIZE_DEFAULT_HEADER * scale;
		float defaultSize = MissedCallConstant.FONT_SIZE_DEFAULT * scale;

		viewHolder.nameTextView
				.setText(TextUtils.isEmpty(callInformation.getCachedName()) == true ? callInformation
						.getNumber()
						: MissedCallConstant.UNKNOWN_PHONE_NUMBER_VALUE
								.equals(callInformation.getNumber()) == true ? this.context
								.getResources().getString(
										R.string.missed_call_unknown)
								: callInformation.getCachedName());
		viewHolder.nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP,
				headerSize);
		viewHolder.numberTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP,
				defaultSize);
		viewHolder.dateTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP,
				defaultSize);
		viewHolder.numberTextView.setText(TextUtils.isEmpty(callInformation
				.getCachedName()) == true ? null : callInformation.getNumber());

		new PhoneLookupAsyncTask(viewHolder, position).execute(callInformation
				.getNumber());
		Long timeDifference = currentTime - callInformation.getDate();

		String dateString = "";
		if (timeDifference >= DAY_IN_MILLISECONDS || timeDifference <= 0) {
			DateFormat dateFormat = DateFormat.getDateInstance();
			dateString = dateFormat.format(new Date(callInformation.getDate()));
		} else if (timeDifference >= HOUR_IN_MILLISECONDS) {
			Long value = timeDifference / HOUR_IN_MILLISECONDS;
			if (value.intValue() == 1) {
				dateString = this.layoutInflater.getContext().getResources()
						.getQuantityString(R.plurals.abbrev_num_hours_ago, 1);
			} else {
				dateString = this.layoutInflater
						.getContext()
						.getResources()
						.getQuantityString(R.plurals.abbrev_num_hours_ago, 2,
								timeDifference / HOUR_IN_MILLISECONDS);
			}
		} else {
			Long value = timeDifference / MINUTE_IN_MILLISECONDS;
			if (value.intValue() == 1) {
				dateString = this.layoutInflater.getContext().getResources()
						.getQuantityString(R.plurals.abbrev_num_minutes_ago, 1);
			} else {
				dateString = this.layoutInflater
						.getContext()
						.getResources()
						.getQuantityString(R.plurals.abbrev_num_minutes_ago, 2,
								timeDifference / MINUTE_IN_MILLISECONDS);
			}
		}

		viewHolder.dateTextView.setText(dateString);

		return convertView;
	}

	static class ViewHolder {
		ImageView missedCallContactImageView;
		TextView nameTextView;
		TextView numberTextView;
		TextView dateTextView;
		ImageButton callButton;
	}

	public class PhoneLookupAsyncTask extends AsyncTask<String, Void, Object[]> {
		MissedCallAdapter.ViewHolder viewHolder;
		int position;

		public PhoneLookupAsyncTask(MissedCallAdapter.ViewHolder viewHolder,
				int position) {
			super();
			this.viewHolder = viewHolder;
			this.position = position;
		}

		@Override
		protected Object[] doInBackground(String... params) {
			String phoneNumber = params[0];
			if (TextUtils.isEmpty(phoneNumber) == false
					&& MissedCallConstant.UNKNOWN_PHONE_NUMBER_VALUE
							.equals(phoneNumber) == false) {
				Cursor contactCursor = null;
				try {
					Uri phoneLookupUri = Uri.withAppendedPath(
							PhoneLookup.CONTENT_FILTER_URI,
							Uri.encode(phoneNumber));
					contactCursor = context.getContentResolver().query(
							phoneLookupUri,
							new String[] { PhoneLookup.DISPLAY_NAME,
									ContactsContract.Contacts._ID,
									Contacts.PHOTO_ID }, null, null, null);
					if (contactCursor != null
							&& contactCursor.moveToNext() == true) {
						String displayName = contactCursor.getString(0);
						Long contactId = contactCursor.getLong(1);
						Integer photoId = contactCursor.getInt(2);
						return new Object[] { phoneNumber, displayName,
								contactId, photoId };
					} else {
						return new Object[] { phoneNumber };
					}
				} finally {
					if (contactCursor != null) {
						contactCursor.close();
					}
				}
			} else {
				return null;
			}
		}

		@Override
		protected void onPostExecute(Object[] result) {
			super.onPostExecute(result);

			if (result != null) {
				if (result.length > 1) {
					String displayName = result[1].toString();
					viewHolder.nameTextView.setText(displayName);
					viewHolder.numberTextView.setText(result[0].toString());

					callInformations.get(this.position).setCachedName(
							displayName);

					if (result[2] != null
							&& TextUtils.isEmpty(result[3].toString()) == false) {
						Long contactId = (Long) result[2];

						Bitmap bitmap = mMemoryCache.get(contactId.toString());
						callInformations.get(this.position).setContactId(
								contactId);
						if (bitmap == null) {
							Uri uri = ContentUris.withAppendedId(
									ContactsContract.Contacts.CONTENT_URI,
									contactId);
							InputStream input = ContactsContract.Contacts
									.openContactPhotoInputStream(
											context.getContentResolver(), uri);
							if (input != null) {
								bitmap = BitmapFactory.decodeStream(input);
								mMemoryCache.put(contactId.toString(), bitmap);
							} else {
								bitmap = defaultContactPictre;
								mMemoryCache.put(contactId.toString(),
										defaultContactPictre);
							}
							try {
								if (input != null) {
									input.close();
								}
							} catch (IOException e) {
								bitmap = mMemoryCache
										.get(IMPOSSIBLE_CONTACT_ID);
								if (bitmap == null) {
									bitmap = defaultContactPictre;
									mMemoryCache.put(IMPOSSIBLE_CONTACT_ID,
											defaultContactPictre);
								}
								viewHolder.missedCallContactImageView
										.setImageBitmap(bitmap);
							}
						}
						viewHolder.missedCallContactImageView
								.setImageBitmap(bitmap);
					}

				} else {
					Bitmap bitmap = mMemoryCache.get(IMPOSSIBLE_CONTACT_ID);
					if (bitmap == null) {
						bitmap = defaultContactPictre;
						mMemoryCache.put(IMPOSSIBLE_CONTACT_ID,
								defaultContactPictre);
					}
					viewHolder.missedCallContactImageView
							.setImageBitmap(bitmap);
					viewHolder.nameTextView.setText(result[0].toString());
					viewHolder.numberTextView.setText("");
				}
			} else {
				Bitmap bitmap = mMemoryCache.get(IMPOSSIBLE_CONTACT_ID);
				if (bitmap == null) {
					bitmap = defaultContactPictre;
					mMemoryCache.put(IMPOSSIBLE_CONTACT_ID,
							defaultContactPictre);
				}
				viewHolder.missedCallContactImageView.setImageBitmap(bitmap);
				viewHolder.nameTextView.setText(context.getResources()
						.getString(R.string.missed_call_unknown));
				viewHolder.numberTextView.setText("");
			}
		}
	}
}
